/*
 * Copyright 2022-2027 中国信息通信研究院云计算与大数据研究所
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package com.service.impl;

import java.math.BigDecimal;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;

import com.common.calculation.AmountUtil;
import com.common.calculation.InitiUtil;
import com.common.constant.AccountConstant;
import com.common.context.SpringContextUtils;
import com.mapper.Transfer;
import com.pojo.Account;
import com.service.IsolationMainService;

@Service
@Scope("prototype")
public class IsolationMainServiceImpl extends Thread implements IsolationMainService{
    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    TransactionDefinition transactionDefinition;
    @Autowired
    private Transfer transfer;
    private final Logger logger = LoggerFactory.getLogger(IsolationMainServiceImpl.class); 
    
    private boolean isStop = false;
    
    private int datacfg_accnum;
    
    /**
     * 数据库隔离级别RR或者RC
     */
    private String isolationLevel;
    
    @Override
	public void run() {
    	logger.info("隔离性检测线程启动了");
    	while(true&&!isStop) {
    		int accountNum = AccountConstant.ACCOUNT_DEFAULT_NUM;
        	BigDecimal money = AmountUtil.getRandomMoney(0,1000);//转账金额
            Random r = new Random();
            String accountFrom = "90"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+((r.nextInt(accountNum )+1)));//借方
            String accountTo = "90"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+((r.nextInt(accountNum )+1)));//贷方
            while(accountFrom.equals(accountTo)) {//保证借方贷方不相等
            	accountTo = "90"+String.valueOf(InitiUtil.getAccnum(datacfg_accnum)+((r.nextInt(accountNum )+1)));
            }
        	Account from = transfer.readAccount(accountFrom);
    		Account to = transfer.readAccount(accountTo);
    		if(from==null) {
    			logger.info("IsolationMainServiceImpl run Account from {} is null ", accountFrom);
    			continue;
    		}
    		if(to==null) {
    			logger.info("IsolationMainServiceImpl run Account to {} is null ", accountTo);
    			continue;
    		}
    		//转账线程初始化
    		IsolationSubServiceImpl isolationSubOne = SpringContextUtils.getBean(IsolationSubServiceImpl.class);
    		isolationSubOne.setFrom(from);
    		isolationSubOne.setTo(to);
    		isolationSubOne.setMoney(money);
    		isolationSubOne.setType("1");
    		//检测线程初始化
    		IsolationSubServiceImpl isolationSubTwo = SpringContextUtils.getBean(IsolationSubServiceImpl.class);
    		isolationSubTwo.setFrom(from);
    		isolationSubTwo.setTo(to);
    		isolationSubTwo.setMoney(money);
    		isolationSubTwo.setType("2");
    		isolationSubTwo.setIsolationLevel(isolationLevel);
    		isolationSubOne.setIsolation(isolationSubTwo);
    		isolationSubTwo.setIsolation(isolationSubOne);
    		isolationSubOne.start();
    		isolationSubTwo.start();
    		try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				logger.error("IsolationMainServiceImpl run InterruptedException accountFrom {} accountTo {} e {}" 
						,accountFrom,accountTo,e);
			}
    	}
    	logger.info("隔离性线程结束了");
	}


	public boolean isStop() {
		return isStop;
	}



	public void setStop(boolean isStop) {
		this.isStop = isStop;
	}



	public Integer getDatacfg_accnum() {
		return datacfg_accnum;
	}



	public void setDatacfg_accnum(Integer datacfg_accnum) {
		this.datacfg_accnum = datacfg_accnum;
	}


	public String getIsolationLevel() {
		return isolationLevel;
	}


	public void setIsolationLevel(String isolationLevel) {
		this.isolationLevel = isolationLevel;
	}
    
    
}